home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / std / c++ / 61 < prev    next >
Encoding:
Internet Message Format  |  1996-08-06  |  3.8 KB

  1. From: "D. Allan Drummond" <allan.drummond@trilogy.com>
  2. Message-ID: <30FCDA77.69CB@trilogy.com>
  3. X-Original-Date: Wed, 17 Jan 1996 05:16:07 -0600
  4. Path: in2.uu.net!bounce-back
  5. Date: 18 Jan 96 02:05:47 GMT
  6. Approved: fjh@cs.mu.oz.au
  7. Newsgroups: comp.std.c++
  8. Subject: An STL helper -- and template and type shenanigans
  9. Organization: Trilogy
  10. X-Mailer: Mozilla 2.0b3 (WinNT; I)
  11. Cc: "std-c++@ncar.ucar.edu"@armadillo.trilogy.com
  12. X-Auth: PGPMoose V1.1 PGP comp.std.c++
  13.     iQBFAgUBMP2rQuEDnX0m9pzZAQEAnwGAi32UgLsDQ1YCWkaJOzwu7n3FD9QJVWiz
  14.     LP1F0BxD27xHyr5pKRzrRu1Hq9p9CP74
  15.     =NuWH
  16.  
  17. In writing an STL helper function, I ran into a snag.  The helper function
  18. is used to make a deep copy of a list of pointers, so that the following
  19. code is possible:
  20.  
  21. #include <list.h>
  22.  
  23. class A {}
  24.  
  25. main()
  26. {
  27.     list<A*> alist;
  28.     // Now add bunches of A*'s to the list...
  29.  
  30.     list<A*> other_alist;
  31.     deep_copy( alist, other_alist );
  32.  
  33.     // Now modify contents of other_alist with impunity --
  34.     // they're distinct from alist's.
  35. }
  36.  
  37.  
  38. Below are the two template functions that do the work.
  39.  
  40. ----------------
  41.  
  42. // deep_copy requires that class T have
  43. // a copy constructor, and for best use, one that
  44. // makes a deep copy.
  45.  
  46. template<class Iter, class ContainedType>
  47. void deep_copy( Iter fromB, Iter fromE, Iter toB, Iter toE, ContainedType* )
  48. {
  49.     while( (fromB != fromE) && (toB != toE) && *fromB )
  50.         *toB++ = new T( **fromB++ );
  51. }
  52.  
  53. template<class Container>
  54. void deep_copy( Container& from, Container& to )
  55. {
  56.     to = from; // expand to make sure TO is as big as FROM.
  57.                // should be cheap, if this is really a list of pointers.
  58.     Container::value_type type;
  59.     deep_copy( from.begin(), from.end(), to.begin(), to.end(), type );
  60. }
  61.  
  62. -----------------
  63.  
  64. Note: STL container classes all have a public typedef like this --
  65.  
  66.     typedef T value_type;
  67.  
  68. The above set of functions will always be run on pointer-lists, where
  69. T is a pointer type.
  70.  
  71. -----------------
  72.  
  73.  
  74. So, the obvious strange item is the ContainedType class in the top template
  75. header.  The problem is that Container::value_type is a pointer type, so I
  76. can't say something like *toB = new Container::value_type( **fromB ) --
  77. that would make the rhs a **, which is not the desired *.
  78.  
  79. The template mechanism has the strange ability to "dereference" types, so
  80. that when I pass a T* to the top function, I can then use the T type
  81. normally.
  82.  
  83. This seems ugly to me.  How can I get access to the type T (not T*) in the
  84. first function, so that I don't have to pass a bogus parameter to some
  85. second function?
  86.  
  87.  
  88. ( For the casual reader: You must use all template types in the function
  89.     arguments.  Consider a silly example:
  90.  
  91.     template<class T, class S> void foo( T t ) { S* s = new S; }
  92.  
  93.     How could the compiler figure out what S was from the following?
  94.  
  95.     A a;
  96.     foo( a ); )
  97.  
  98.  
  99.  
  100. I really want to write something like this (the following code is
  101. nonsensical but should convey the spirit of the idea):
  102.  
  103. template<class Container>
  104. void deep_copy( Container& from, Container& to )
  105. {
  106.     to = from; // expand to make sure TO is as big as FROM.
  107.                // should be cheap, if this is really a list of pointers.
  108.     Container::const_iterator f( from.begin() );
  109.     Container::iterator t( to.begin );
  110.  
  111.     while( (f != from.end()) && (t != to.end()) && *f )
  112.         *t++ = new (*Container::value_type)( **f++ );
  113. }
  114.  
  115. It seems as though there's no REAL reason to have to split it into two
  116. functions, but the "type dereferencing" is crucial.
  117.  
  118. Any suggestions?  Incidentally, the two-function method works great --
  119. feel free to rip it off with impunity.
  120.  
  121.  
  122. Thanks,
  123.  
  124. Allan
  125. allan.drummond@trilogy.com
  126. ---
  127. [ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  128.   Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  129.   is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
  130.